package com.yupi.mianshiya.service.impl;

import cn.hutool.core.util.StrUtil;
import com.yupi.mianshiya.service.LikeService;
import org.redisson.api.RAtomicLong;
import org.redisson.api.RScript;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Arrays;

@Service
public class LikeServiceImpl implements LikeService {


    public static final String LIKE_SET_KEY   = "article:liked:{}";
    public static final String LIKE_COUNT_KEY = "article:likeCount:{}";

    @Resource
    private RedissonClient redissonClient;


    @Override
    public Long toggleLike(Long userId, Long articleId) {
        String luaScript =
                "local likeKey = KEYS[1] " +
                        "local countKey = KEYS[2] " +
                        "local userId = ARGV[1] " +
                        "local exists = redis.call('EXISTS', likeKey) " + // 添加存在检查
                        "if exists == 0 then " + // 键不存在时初始化
                        "   redis.call('SADD', likeKey, '') " + // 创建空集合
                        "   redis.call('SET', countKey, 0) " + // 初始化计数器
                        "end " +
                        "local isMember = redis.call('SISMEMBER', likeKey, userId) " +
                        "if isMember == 1 then " +
                        "   redis.call('SREM', likeKey, userId) " +
                        "   local count = redis.call('DECR', countKey) " +
                        "   if count < 0 then redis.call('SET', countKey, 0) end " +
                        "   return count " +
                        "else " +
                        "   redis.call('SADD', likeKey, userId) " +
                        "   return redis.call('INCR', countKey) " +
                        "end";

        String likeKey = StrUtil.format(LIKE_SET_KEY, articleId);
        String countKey = StrUtil.format(LIKE_COUNT_KEY, articleId);

        return redissonClient.getScript().eval(
                RScript.Mode.READ_WRITE,
                luaScript,
                RScript.ReturnType.INTEGER,
                Arrays.asList(likeKey, countKey),
                userId.toString()
        );
    }


    /**
     * 获取点赞状态
     */
    @Override
    public Boolean getLikeStatus(Long userId, Long articleId) {
        String luaScript =
                "local likeKey = KEYS[1] " +
                        "local userId = ARGV[1] " +
                        "if redis.call('EXISTS', likeKey) == 0 then " +
                        "   return 0 " + // 键不存在返回0
                        "end " +
                        "return redis.call('SISMEMBER', likeKey, userId)";

        String likeKey = StrUtil.format(LIKE_SET_KEY, articleId);

        Long result = redissonClient.getScript().eval(
                RScript.Mode.READ_ONLY,
                luaScript,
                RScript.ReturnType.INTEGER,
                Arrays.asList(likeKey),
                userId.toString()
        );

        return result != null && result == 1;
    }

    /**
     * 获取点赞数
     */
    @Override
    public Long getLikeCount(Long articleId) {
        String countKey = StrUtil.format(LIKE_COUNT_KEY, articleId);
        RAtomicLong counter = redissonClient.getAtomicLong(countKey);

        // 处理键不存在的情况
        if (!counter.isExists()) {
            return 0L;
        }

        return counter.get();
    }

}
